package com.fh.util;


import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.stream.Collectors;

import com.ybd.common.mask.MaskTypeEnum;
import com.ybd.common.mask.MaskUtils;
import org.apache.commons.codec.binary.Base64;

/**
 * 创建者：shanlin
 * 创建时间：2017/8/26 10:44
 **/
public class CoverUtil {
    
    /**
     * 是否加密  1 = 加密  0 = 不加密
     * 第一位 是否委内加密
     * 第二位 是否委内 手机 加密
     * 第三位 是否委内 身份证 加密
     * 第四位 是否委外加密
     * 第五位 是否委外 手机 加密
     * 第六位 是否委外 身份证 加密
     */
    public static Boolean isCoverGet(int index){
        String o =  Const.COVER_CONST;
        int len = o.length();
        if(index > len){
            index = len;
        }else if(index <= 0){
            index = 1 ;
        }
        return BitStatesUtils.hasState(o,index);
    }
    
    /**
     *  以下角色数据不加密
     * @return
     */
    private static boolean hasRoleOnCover(){
        String role_ID = UserUtils.getRealUser().getROLE_ID();
        if(role_ID.equals(Const.ROLE_CSJL)){
            //催收经理
            return  true;
        }else if(role_ID.equals(Const.ADMIN)){
            //admin
            return  true;
        }
        return false;
    }

    /**
     * 掩码 手机号
     *
     * @param mobile
     * @return
     */
    public static String mobile(String mobile) {
        return coverIng(mobile, MaskTypeEnum.MOBILE);
    }

    /**
     * 掩码 银行卡号
     *
     * @param bankCard
     * @return
     */
    public static String bankCard(String bankCard) {
        return coverIng(bankCard, MaskTypeEnum.BANKCARD);
    }

    /**
     * 掩码 身份证号
     *
     * @param idCard
     * @return
     */
    public static String IdCard(String idCard) {
        return coverIng(idCard, MaskTypeEnum.IDCARD);
    }
    
    /**
     * 掩码 身份证号2
     *
     * @param idCard
     * @return
     */
    public static String IdCard2(String idCard) {
        return coverIng(idCard, MaskTypeEnum.IDCARD2);
    }
    /**
     * 掩码 地址
     *
     * @param address
     * @return
     */
    public static String Address(String address) {
        return coverIng(address, MaskTypeEnum.ADDRESS);
    }

    public static String coverIng(String cover, MaskTypeEnum type) {
        if(hasRoleOnCover()){
            return cover;
        }
        if(isCoverGet(1)){
            if(isCoverGet(2) && Objects.equals(type,MaskTypeEnum.MOBILE)){
                return MaskUtils.maskType2String(cover, type);
            }
            if(isCoverGet(3) && Objects.equals(type,MaskTypeEnum.IDCARD2)){
                return MaskUtils.maskType2String(cover, type);
            }
            return cover;
        }else if(!isCoverGet(1)){
            return cover;
        }
        return MaskUtils.maskType2String(cover, type);
    }

    /**
     * 针对单个bean的单个字段进行掩码
     *
     * @param t
     * @param property
     * @param type
     * @param <T>
     * @return
     */
    public static <T> T setBeanCover(T t, String property, MaskTypeEnum type) {
        try {
            if (t instanceof Map) {
                //map类型
                ((Map) t).put(property, coverIng((String) ((Map) t).get(property), type));
            } else {//实体类
                Class<T> c = (Class<T>) t.getClass();
                Field field = c.getDeclaredField(property);
                field.setAccessible(true);
                field.set(t,coverIng((String)field.get(t),type));
                field.setAccessible(false);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return t;
    }

    /**
     * 针对单个bean的多个字段进行掩码
     *
     * @param t
     * @param properties
     * @param <T>
     * @return
     */
    public static <T> T setBeanCover(T t, Map<String, MaskTypeEnum> properties) {
        for (Map.Entry<String, MaskTypeEnum> entry : properties.entrySet()) {
            setBeanCover(t, entry.getKey(), entry.getValue());
        }
        return t;
    }

    /**
     * 针对list中的bean的单个字段进行掩码
     *
     * @param tList
     * @param property
     * @param type
     * @param <T>
     * @return
     */
    public static <T> List<T> setListCover(List<T> tList, String property, MaskTypeEnum type) {
        Consumer action = (x -> setBeanCover(x, property, type));
        tList.stream().peek(action).collect(Collectors.toList());
        return tList;

    }

    /**
     * 针对list中的bean的多个字段进行掩码
     *
     * @param tList
     * @param properties
     * @param <T>
     * @return
     */
    public static <T> List<T> setListCover(List<T> tList, Map<String, MaskTypeEnum> properties) {
        for (Map.Entry<String, MaskTypeEnum> entry : properties.entrySet()) {
            setListCover(tList, entry.getKey(), entry.getValue());
        }
        return tList;
    }
    /******************************************************************************************************************/

    public static String coverIngAO(String cover, MaskTypeEnum type) {
        if(isCoverGet(4)){
            if(isCoverGet(5) && Objects.equals(type,MaskTypeEnum.MOBILE)){
                return MaskUtils.maskType2String(cover, type);
            }
            if(isCoverGet(6) && Objects.equals(type,MaskTypeEnum.IDCARD2)){
                return MaskUtils.maskType2String(cover, type);
            }
            return cover;
        }else if(!isCoverGet(4)){
            return cover;
        }
        return MaskUtils.maskType2String(cover, type);
    }
    /**
     * 针对委外加密 (方法名以AO结尾)
     */
    public static <T> T setBeanCoverAO(T t, String property, MaskTypeEnum type) {
        try {
            if (t instanceof Map) {
                    ((Map) t).put(property, coverIngAO((String) ((Map) t).get(property), type));
            } else {//实体类
                Class<T> c = (Class<T>) t.getClass();
                Field field = c.getDeclaredField(property);
                field.setAccessible(true);
                field.set(t,coverIngAO((String)field.get(t),type));
                field.setAccessible(false);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return t;
    }
    /**
     * 针对单个bean的多个字段进行掩码
     *
     * @param t
     * @param properties
     * @param <T>
     * @return
     */
    public static <T> T setBeanCoverAO(T t, Map<String, MaskTypeEnum> properties) {
        for (Map.Entry<String, MaskTypeEnum> entry : properties.entrySet()) {
            setBeanCoverAO(t, entry.getKey(), entry.getValue());
        }
        return t;
    }

    /**
     * 针对list中的bean的单个字段进行掩码
     *
     * @param tList
     * @param property
     * @param type
     * @param <T>
     * @return
     */
    public static <T> List<T> setListCoverAO(List<T> tList, String property, MaskTypeEnum type) {
        Consumer action = (x -> setBeanCoverAO(x, property, type));
        tList.stream().peek(action).collect(Collectors.toList());
        return tList;

    }

    /**
     * 针对list中的bean的多个字段进行掩码
     *
     * @param tList
     * @param properties
     * @param <T>
     * @return
     */
    public static <T> List<T> setListCoverAO(List<T> tList, Map<String, MaskTypeEnum> properties) {
        for (Map.Entry<String, MaskTypeEnum> entry : properties.entrySet()) {
            setListCoverAO(tList, entry.getKey(), entry.getValue());
        }
        return tList;
    }



    /******************************************************************************************************************/

    private String id;

    private String name1;

    private String name2;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName1() {
        return name1;
    }

    public void setName1(String name1) {
        this.name1 = name1;
    }

    public String getName2() {
        return name2;
    }

    public void setName2(String name2) {
        this.name2 = name2;
    }

    @Override
    public String toString() {
        return "CoverUtil{" +
                "id='" + id + '\'' +
                ", name1='" + name1 + '\'' +
                ", name2='" + name2 + '\'' +
                '}';
    }

    public static void main(String[] args) {
//        System.out.println(coverIng("321284169111201810", MaskTypeEnum.IDCARD));
//        System.out.println(coverIng("321284169111201810", MaskTypeEnum.IDCARD));
//        System.out.println(mobile("13524929813"));
//        System.out.println(bankCard("6225760013150110"));
//        System.out.println(IdCard("321284199110201810"));
//        System.out.println(Address("河南省平顶山市卫东区建设东路13号院"));
//        System.out.println(coverIng("河南省平顶山市卫东区建设东路13号院", MaskTypeEnum.ADDRESS));
//        System.out.println(coverIng("6225760013150110", MaskTypeEnum.BANKCARD));
//        System.out.println(coverIng("河南中评能花集团股份有限公司", MaskTypeEnum.COMPANY));
//        System.out.println(coverIng("321284199110201810", MaskTypeEnum.IDCARD));
//        System.out.println(coverIng("321284199110201810", MaskTypeEnum.IDCARD));
//        System.out.println(coverIng("13524929813", MaskTypeEnum.MOBILE));
//        System.out.println(coverIng("赵荣磊", MaskTypeEnum.USERNAME));

      /*   static <T> T setBeanCover(T t,String property,MaskTypeEnum type)
        List<CoverUtil> list = new ArrayList<>();
        CoverUtil a1 = new CoverUtil();
        a1.setId("1");
        a1.setName1("15802333696");
        a1.setName2("15700002222");
        CoverUtil a2 = new CoverUtil();
        a2.setId("2");
        a2.setName1("15600009999");
        a2.setName2("15566669999");
        CoverUtil a3 = new CoverUtil();
        a3.setId("3");
        a3.setName1("15488886666");
        a3.setName2("15366645235");
        list.add(a1);
        list.add(a2);
        list.add(a3);
        Map<String,MaskTypeEnum> map = new HashMap<>();
        map.put("name1",MaskTypeEnum.MOBILE);
        map.put("name2",MaskTypeEnum.MOBILE);
//        System.out.println(a1);
        System.out.println(setBeanCover(a1,"name1",MaskTypeEnum.MOBILE));
//        System.out.println(setBeanCover(a1,map));
//        System.out.println(list);
//        System.out.println(setListCover(list,"name1",MaskTypeEnum.MOBILE));
//        System.out.println(setListCover(list,map));
//        Map<String,String> s = new HashMap<>();
//        s.put("name1","15806122913");
//        s.put("name2","15366662222");
//        List<Map<String,String>> ss = new ArrayList<>();
//        ss.add(s);
//        System.out.println(setBeanCover(s,"name1",MaskTypeEnum.MOBILE));
//        System.out.println(setBeanCover(s,map));
//        System.out.println(setListCover(ss,map));
    }
    */
        int[] a = {26, 5, 98, 108, 28, 99, 100, 56, 34, 1 };
        printArray("排序前：",a);
        MergeSort(a);
        printArray("排序后：",a);
        System.out.println("丈夫|妻子|老公|老婆|父亲|母亲|爸爸|妈妈|老爸|老妈".matches(null));
    }
    static int number=0;
    private static void printArray(String pre,int[] a) {
        System.out.print(pre+"\n");
        for(int i=0;i<a.length;i++)
            System.out.print(a[i]+"\t");
        System.out.println();
    }

    private static void MergeSort(int[] a) {
        // TODO Auto-generated method stub
        System.out.println("开始排序");
        Sort(a, 0, a.length - 1);
    }

    private static void Sort(int[] a, int left, int right) {
        if(left>=right)
            return;

        int mid = (left + right) / 2;
        //二路归并排序里面有两个Sort，多路归并排序里面写多个Sort就可以了
        Sort(a, left, mid);
        Sort(a, mid + 1, right);
        merge(a, left, mid, right);

    }


    private static void merge(int[] a, int left, int mid, int right) {

        int[] tmp = new int[a.length];
        int r1 = mid + 1;
        int tIndex = left;
        int cIndex=left;
        // 逐个归并
        while(left <=mid && r1 <= right) {
            if (a[left] <= a[r1])
                tmp[tIndex++] = a[left++];
            else
                tmp[tIndex++] = a[r1++];
        }
        // 将左边剩余的归并
        while (left <=mid) {
            tmp[tIndex++] = a[left++];
        }
        // 将右边剩余的归并
        while ( r1 <= right ) {
            tmp[tIndex++] = a[r1++];
        }




        System.out.println("第"+(++number)+"趟排序:\t");
        // TODO Auto-generated method stub
        //从临时数组拷贝到原数组
        while(cIndex<=right){
            a[cIndex]=tmp[cIndex];
            //输出中间归并排序结果
            System.out.print(a[cIndex]+"\t");
            cIndex++;
        }
        System.out.println();
    }
    
    public static String decodeStr(String encodeStr){
        byte[] b=encodeStr.getBytes();
        Base64 base64=new Base64();
        b=base64.decode(base64.decode(b));
        String s=new String(b);
        return s;
    }

}
